package com.csdware.mdviewer;

import static com.csdware.mdviewer.lib_Nanohttpd.protocols.http.response.Response.newChunkedResponse;
import static com.csdware.mdviewer.lib_Nanohttpd.protocols.http.response.Response.newFixedLengthResponse;

import android.content.Context;

import com.csdware.mdviewer.lib_Nanohttpd.protocols.http.IHTTPSession;
import com.csdware.mdviewer.lib_Nanohttpd.protocols.http.NanoHTTPD;
import com.csdware.mdviewer.lib_Nanohttpd.protocols.http.response.Response;
import com.csdware.mdviewer.lib_Nanohttpd.protocols.http.response.Status;
import com.google.gson.JsonObject;

import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

public class Service_HttpServer extends NanoHTTPD {

    private final Context context;
    private final String ServerRootPath; // 服务器根目录在com/csdware/mdviewer/assets/中的相对路径
    private final String ServedNotePath;
    private SharedPreferences sharedPreferences;

    public Service_HttpServer(Context context, String ServerIP, int port, String ServerRootPath, String ServedNotePath) {
        super(ServerIP, port);  // 允许局域网所有设备访问
        sharedPreferences = context.getSharedPreferences("Settings", Context.MODE_PRIVATE);
        this.context = context;
        // 确保根路径格式正确（不包含前后斜杠）
        this.ServerRootPath = ServerRootPath.replaceAll("^/|/$", "");
        this.ServedNotePath = ServedNotePath;
    }

    @Override
    public Response serve(IHTTPSession session) {
        String uri = session.getUri();  // 获取请求路径（如"/index.html"或"/js/main.js"），注意在 HTTP 协议中，加号会被解系为空格
        switch (uri) {
            case "/NoteTheme.css":

                if (sharedPreferences.getString("CSSPath", "").isEmpty()) {
                    try {
                        String assetPath = ServerRootPath + "/NoteTheme.css";
                        AssetManager assetManager = context.getAssets();
                        InputStream CommonWebpageSourceInputStream = assetManager.open(assetPath);
                        return newChunkedResponse(Status.OK, "text/css", CommonWebpageSourceInputStream);
                    } catch (IOException e) {  // 文件不存在或读取失败
                        return newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "MD source not found: " + e.getMessage());
                    }
                } else {
                    try {
                        File file = new File(sharedPreferences.getString("CSSPath", ""));
                        StringBuilder contentBuilder = new StringBuilder();
                        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
                        String line;
                        while ((line = br.readLine()) != null) contentBuilder.append(line).append(System.lineSeparator());
                        return newFixedLengthResponse(Status.OK, "text/css", contentBuilder.toString());
                    } catch (IOException e) {  // 文件不存在或读取失败
                        return newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "MD source not found: " + e.getMessage());
                    }
                }
            case "/POST_GetMarkdownSource":
                try {
                    File file = new File(ServedNotePath);
                    StringBuilder contentBuilder = new StringBuilder();
                    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8));
                    String line;
                    while ((line = br.readLine()) != null) contentBuilder.append(line).append(System.lineSeparator());
                    return newFixedLengthResponse(Status.OK, "application/json", contentBuilder.toString());
                } catch (IOException e) {  // 文件不存在或读取失败
                    return newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "MD source not found: " + e.getMessage());
                }
            default:
                try {
                    String assetPath = ServerRootPath + uri;  // 构建assets中的实际路径（如"LocalWebServerAssets/index.html"）
                    if (!isPathSafe(assetPath)) return newFixedLengthResponse(Status.FORBIDDEN, "text/plain", "path not safe");  // 检查路径安全性（防止目录遍历攻击）
                    AssetManager assetManager = context.getAssets();
                    InputStream CommonWebpageSourceInputStream = assetManager.open(assetPath);
                    return newChunkedResponse(Status.OK, getMimeType(assetPath), CommonWebpageSourceInputStream);
                } catch (IOException e) {  // 上述读取出现了错误，说明客户端可能是想访问笔记的附件文件
                    String ServedNoteRootDir = new File(ServedNotePath).getParent();
                    String AttachmentPath = ServedNoteRootDir + uri;
                    try {
                        return newChunkedResponse(Status.OK, getMimeType(uri), new FileInputStream(AttachmentPath));
                    } catch (FileNotFoundException e2) {
                        return newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "attachment not found: " + e.getMessage());
                    }
                }
        }
    }

    private boolean isPathSafe(String path) {
        // 检查路径安全性，防止目录遍历攻击：禁止包含"../"的路径（防止访问上级目录）
        return !path.contains("../") && !path.contains("..\\");
    }

    private String getMimeType(String fileName) {  // 根据文件名获取MIME类型
        if (fileName.endsWith("+esm")) return "application/javascript";
        if (fileName.endsWith(".html")) return "text/html";
        if (fileName.endsWith(".css")) return "text/css";
        if (fileName.endsWith(".js")) return "application/javascript";
        if (fileName.endsWith(".json")) return "application/json";
        if (fileName.endsWith(".png")) return "image/png";
        if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) return "image/jpeg";
        if (fileName.endsWith(".gif")) return "image/gif";
        if (fileName.endsWith(".txt")) return "text/plain";
        return "application/octet-stream";  // 默认二进制流
    }
}